// CWEdit.cpp : implementation file
//

#include "stdafx.h"
#include "assit.h"
#include "CWEdit.h"
#include "CWCheckbox.h"
#include "AssitTreeNode.h"
#include "assitView.h"
#include "CWDateTime.h"


// CWEdit

IMPLEMENT_DYNAMIC(CWEdit, CEdit)

CWEdit::CWEdit(CWEdit* pParent, CWEdit* pPrev, CWEdit* pNext, int depth)
{
	m_pCheckBox = NULL;
	m_pLabel = NULL;
	m_depth = depth;
	m_pParent = pParent;
	m_pPrev = pPrev;
	m_pNext = pNext;
	m_pFont = NULL;
	m_textColor = RGB(0,0,0);
}

CWEdit::~CWEdit()
{
	delete m_pFont;
}


BEGIN_MESSAGE_MAP(CWEdit, CEdit)
	ON_WM_CHAR()
	ON_WM_SETFOCUS()
	ON_WM_KILLFOCUS()
	ON_WM_CREATE()
	ON_WM_CTLCOLOR_REFLECT()
	ON_WM_KEYDOWN()
END_MESSAGE_MAP()



// CWEdit message handlers




BOOL CWEdit::PreTranslateMessage(MSG* pMsg)
{
	// TODO: Add your specialized code here and/or call the base class

	return CEdit::PreTranslateMessage(pMsg);
}

void CWEdit::MoveControl(CWnd* pWnd, int distanceX)
{
	RECT thisRect;
	pWnd->GetClientRect(&thisRect);
	pWnd->ClientToScreen(&thisRect);
	pWnd->GetParent()->ScreenToClient(&thisRect);

	//if(::GetKeyState( VK_SHIFT )< 0)

	thisRect.left += distanceX;
	thisRect.right +=distanceX;

	pWnd->MoveWindow(&thisRect, TRUE);
}

void CWEdit::setTextColor(COLORREF color)
{
	m_textColor = color;
	Invalidate();
	UpdateWindow();
}

void CWEdit::AutoSize(CString& strWndText)
{
    if (!::IsWindow(GetSafeHwnd())) 
        return;
 
    // Get the current window position
    CRect rect;
    GetWindowRect(rect);
 
    CWnd* pParent = GetParent();
    if (pParent)
        pParent->ScreenToClient(rect);
  
    CDC* pDC = GetDC();
    CFont* pOldFont = pDC->SelectObject(m_pFont);
    CSize Extent;
	//Use the space character width as default.
	if(strWndText.IsEmpty())
		strWndText = L" ";

	Extent = pDC->GetTextExtent(strWndText);
	Extent.cx += 10;
	Extent.cy += 4;
	
    pDC->SelectObject(pOldFont);
    ReleaseDC(pDC);
 

    // Get the text justification via the window style
    DWORD dwStyle = GetStyle();
 
    // Recalc the window size and position based on the text justification
    if (dwStyle & SS_CENTERIMAGE)
        rect.DeflateRect(0, (rect.Height() - Extent.cy)/2);
    else
        rect.bottom = rect.top + Extent.cy;
 
    if (dwStyle & SS_CENTER)   
        rect.DeflateRect((rect.Width() - Extent.cx)/2, 0);
    else if (dwStyle & SS_RIGHT) 
        rect.left  = rect.right - Extent.cx;
    else // SS_LEFT = 0, so we can't test for it explicitly 
        rect.right = rect.left + Extent.cx;
 
    // Move the window
    SetWindowPos(NULL, rect.left, rect.top, rect.Width(), rect.Height(), SWP_NOZORDER);
}

void CWEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
	CWnd* pParent = GetParent();
	if(!pParent->IsKindOf(RUNTIME_CLASS(CWaiTreeNode)))
	{
		CEdit::OnChar(nChar, nRepCnt, nFlags);
		return;
	}

	CWaiTreeNode* pTreeNode = (CWaiTreeNode*)pParent;
	CwaiView* pView = (CwaiView*)pTreeNode->GetParent();
	XMLNode* node = pTreeNode->getTreeNode();
	CXMLDoc* pXMLDoc = pView->getXMLDoc();

	if(nChar == VK_BACK)
	{
		if(0 == this->GetWindowTextLengthW())
		{
			XMLNode* parent = node->Parent();
			if(parent)
			{
				CWaiTreeNode* focusNode = pTreeNode->PreviousSibling()?pTreeNode->PreviousSibling():
					pTreeNode->GetParentNode();

				parent->DeleteChild(node);
				//Potential issue, self deleted.
				pTreeNode->RemoveSelfFromTree();
				pView->SendMessage(WM_RELOADTREEDATA);
				focusNode->setEditFocus();
				return;
			}

		}
	}
	// TODO: Add your message handler code here and/or call default
	if(nChar == '\r' || nChar == '\n')
	{
		XMLNode* pNode = pXMLDoc->insertSibling(node, "");
		CWaiTreeNode* pSibing = pTreeNode->InsertSibling();
		pSibing->setTreeNode(pNode);

		pTreeNode->killEditFocus();
		pView->SendMessage(WM_RELOADTREEDATA);
		pSibing->setEditFocus();
		pView->ScrollToFocusNode(pSibing);
		return;
	}
	//Slash
	if(nChar == VK_HELP)
	{
		CString wsText;
		GetWindowText(wsText);
		if(!wsText.IsEmpty() && wsText.Right(1) == VK_HELP)
		{
			pTreeNode->killEditFocus();

			CWDateTime* pDateTime = new CWDateTime();
			DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_TABSTOP | DTS_LONGDATEFORMAT;
			CRect rect;
			CPoint pos = PosFromChar(wsText.GetLength()?wsText.GetLength()-1:0);
			rect.left = pos.x+10;
			rect.top = pos.y;
			rect.right = rect.left + 150;
			rect.bottom = rect.top + 25;

			ClientToScreen(rect);
			this->GetParent()->ScreenToClient(rect);

			pDateTime->Create(dwStyle, rect, this->GetParent(), GetWindowID());
			pDateTime->ShowWindow(SW_SHOW);
			pDateTime->SetFocus();

			wsText = wsText.Left(wsText.GetLength()-1);
			SetWindowText(wsText);
			AutoSize(wsText);
			return;
		}
	}

	//tab
	if(nChar == VK_TAB)
	{
		if(::GetKeyState( VK_SHIFT )< 0)
		{
			XMLNode* parent = node->Parent();
			XMLNode* root = pXMLDoc->getRoot();
			if(parent == root)
				return;
			XMLNode* grandpa = parent->Parent();
			XMLNode* xmlNode = grandpa->InsertAfterChild(parent, node);

			CWaiTreeNode* pParent = pTreeNode->GetParentNode();
			if(pParent)
			{
				pParent->InsertSibling(pTreeNode);
				pTreeNode->setTreeNode(xmlNode);
			}
		}
		else
		{
			XMLNode* prevSibling = node->PreviousSibling();
			if(!prevSibling)
			{
				return;
			}
			XMLNode* xmlNode = prevSibling->InsertEndChild(node);

			CWaiTreeNode* pNode = pTreeNode->PreviousSibling();
			if(pNode)
			{
				pNode->InsertEndChild(pTreeNode);
				pTreeNode->setTreeNode(xmlNode);
			}
			
		}
		pView->SendMessage(WM_RELOADTREEDATA);
		pTreeNode->setEditFocus();
		return;
	}
	
	// Get the size of the window text
    CString strWndText;
    GetWindowText(strWndText);
	for(int i=0; i<nRepCnt; i++)
		strWndText += (wchar_t)nChar;

	AutoSize(strWndText);
	//The only way that currently found to refresh the parent.
	pTreeNode->ShowWindow(SW_HIDE);
	pTreeNode->ShowWindow(SW_SHOW);

	CEdit::OnChar(nChar, nRepCnt, nFlags);
}


void CWEdit::OnSetFocus(CWnd* pOldWnd)
{
	CEdit::OnSetFocus(pOldWnd);
	// TODO: Add your message handler code here
}


void CWEdit::OnKillFocus(CWnd* pNewWnd)
{
	CEdit::OnKillFocus(pNewWnd);
	// TODO: Add your message handler code here
	CWnd* pParent = GetParent();
	if(pParent->IsKindOf(RUNTIME_CLASS(CWaiTreeNode)))
	{
		CWaiTreeNode* pTreeNode = (CWaiTreeNode*)GetParent();
		pTreeNode->saveContent();
	}
}

void CWEdit::UpdateLabel()
{
	CString string;
	string.Format(L".%i", m_depth+1);
	CString	csLabel = string;
	CWEdit* pParent = m_pParent;
	while(pParent)
	{
		string.Format(L".%i",pParent->m_depth+1);
		csLabel = string+csLabel;
		pParent = pParent->m_pParent;
	}
	csLabel = csLabel.Right(csLabel.GetLength() - 1);
	if(m_pLabel)
		m_pLabel->SetWindowText(csLabel);
}

int CWEdit::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CEdit::OnCreate(lpCreateStruct) == -1)
		return -1;


	    LOGFONT lf;
        memset(&lf,0,sizeof(LOGFONT));
        wcscpy_s(lf.lfFaceName, _countof(lf.lfFaceName), L"Segoe UI");
        m_pFont = new CFont;
        if(!m_pFont->CreateFontIndirect(&lf))
        {
			return 0;
        }
        SetFont(m_pFont);
#if 0
	RECT rect;
	this->GetClientRect(&rect);
	ClientToScreen(&rect);
	this->GetParent()->ScreenToClient(&rect);

	int width = rect.right-rect.left;
	int height = rect.bottom-rect.top;

	CRect rectCheckbox;
	rectCheckbox.bottom = rect.bottom+5;
	rectCheckbox.top = rect.top-5;
	rectCheckbox.left = rect.left-20;
	rectCheckbox.right = rect.left-5;
	m_pCheckBox = new CWCheckbox();
	m_pCheckBox->Create(L"",WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX,rectCheckbox,this->GetParent(),WM_USER+2); 
#endif
	return 0;
}


HBRUSH CWEdit::CtlColor(CDC* pDC, UINT nCtlColor)
{
	// TODO:  Change any attributes of the DC here
	pDC->SetBkMode(TRANSPARENT);
	pDC->SetTextColor(m_textColor);
	// TODO:  Return a non-NULL brush if the parent's handler should not be called
	HBRUSH B = CreateSolidBrush(RGB(255,255,255));
	return B;
}


void CWEdit::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
	// TODO: Add your message handler code here and/or call default
	CWaiTreeNode* pTreeNode = (CWaiTreeNode*)GetParent();
	if(!pTreeNode->IsKindOf(RUNTIME_CLASS(CWaiTreeNode)))
	{
		CEdit::OnKeyDown(nChar, nRepCnt, nFlags);
		return;
	}

	CwaiView* pView = (CwaiView*)pTreeNode->GetParent();
	if(VK_UP == nChar)
	{
		CWaiTreeNode* focusNode = pTreeNode->PreviousSibling();
		if(focusNode)
		{
			focusNode->setEditFocus();
			pView->ScrollToFocusNode(focusNode);
			return;
		}
	}
	if(VK_DOWN == nChar)
	{
		CWaiTreeNode* focusNode = pTreeNode->NextSibing();
		if(focusNode)
		{
			focusNode->setEditFocus();
			pView->ScrollToFocusNode(focusNode);
			return;
		}
	}

	CEdit::OnKeyDown(nChar, nRepCnt, nFlags);
}
